<?php

/**
 * HTML布局帮手
 *
 * @author edikud
 * @package Element
 * @copyright Copyright (c) 2019 Cola (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */
 
class Element
{
    /**
     * 标签名称
     *
     * @access private
     * @var string
     */
    protected $_tagName;

    /**
     * 表单属性列表
     *
     * @access private
     * @var array
     */
    protected $_attr = array();

    /**
     * 是否闭合
     *
     * @access private
     * @var boolean
     */
    protected $_close;

    /**
     * 是否强制自闭合
     *
     * @access protected
     * @var boolean
     */
    protected $_forceClose = NULL;
	
    /**
     * 内部数据/元素列表
     *
     * @access private
     * @var array
     */
    protected $_elements = array();

    /**
     * @api
     *
     * @param string $tagName
     */
    public function __construct($tagName = NULL, array $attributes = NULL)
    {
        $this->_tagName = $tagName;
        if (!empty($attributes)) {
            $this->setAttr($attributes);
        }
    }

    /**
     * @api
     *
     * @param string $name The attribute
     * @param string $value     Its value
     *
     * @return self
     */
    public function setAttr($name, $value = null)
    {
        if (is_array($name)) {
            foreach ($name as $k => $v) {
                $this->_attr[$k] = $v;
            }
        } else {
            $this->_attr[$name] = $value;
        }
        return $this;
    }

    /**
     * @api
     *
     * @param string $name
     *
     * @return self
     */
    public function removeAttr($name)
    {
        if (array_key_exists($name, $this->_attr)) {
            unset($this->_attr[$name]);
        }

        return $this;
    }

    /**
     * @api
     *
     * @param string $name
     *
     * @return string|null
     */
    public function getAttr($name = null)
    {
		return isset($this->_attr[$name]) ? $this->_attr[$name] : NULL;
    }
	
    /**
     * 为匹配的元素添加指定的类名
     * @param string $value
     * @return static instance
     */
    public function addClass($value)
    {
		$classString = (!empty($this->_attr['class']) ? $this->_attr['class'] : '') . ' ' . $value;
		
		if($classString){
			$this->_attr['class'] = implode(' ', array_keys(array_flip(array_filter(explode(' ', $classString)))));
		}

        return $this;
    }

    /**
     * 从匹配的元素中删除指定的类名
     * @param string $value
     * @return static instance
     */
    public function removeClass($value)
    {
		$classString = !empty($this->_attr['class']) ? $this->_attr['class'] : '';

        $oldClassArray = array_filter(explode(' ', $classString));
        $newClassArray = array_filter(explode(' ', $value));	

        $this->_attr['class'] = implode(' ', array_diff($oldClassArray, $newClassArray));

        return $this;
    }
	
    /**
     * 设置属性
     *
     * @access public
     * @param string $name 属性名称
     * @param string $value 属性值
     * @return void
     */
    public function __set($name, $value)
    {
        $this->_attr[$name] = $value;
    }

    /**
     * 获取属性
     *
     * @access public
     * @param string $name 属性名称
     * @return void
     */
    public function __get($name)
    {
        return isset($this->_attr[$name]) ? $this->_attr[$name] : NULL;
    }
	
    /**
     * @api
     *
     * @param string $element
     *
     * @return self
     */
    public function setTagName($tagName)
    {
        $this->_tagName = $tagName;
        return $this;
    }

    /**
     * 设置是否自闭合
     *
     * @access public
     * @param boolean $close 是否自闭合
     * @return Element
     */
    public function setClose($close)
    {
        $this->_forceClose = !!$close;
        return $this;
    }

    /**
     * @api
     *
     * @param string $content
     */
    public function reset()
    {
		$this->_elements = array();
        return $this;
    }
	
    /**
     * 增加元素
     *
     * @access public
     * @param mixed  $element    Element object or String
     * @param $name name
     * @param string $after 在某个元素之后
     * @return Element
     */
    public function set($element, $name = NULL, $after = NULL)
    {
		if(NULL !== $after && isset($this->_elements[$after])){
			!is_string($name) ? $this->_elements[$after][] = $element : $this->_elements[$after][$name] = $element;
		} else {
			!is_string($name) ? $this->_elements[] = $element : $this->_elements[$name][$name] = $element;
		}
		return $this;
    }
	
    /**
     * @api
     *
     * @return Element[]
     */
    public function get($key = null)
    {
		return isset($this->_elements[$key]) ? $this->_elements[$key][$key] : NULL;
    }

    /**
     * @return string
     */
    public function render()
    {
        if (empty($this->_elements)) {
            $this->_close = true;
        }

        if (NULL !== $this->_forceClose) {
            $this->_close = $this->_forceClose;
        }
		
        /** 输出标签 */
        $html = $this->_tagName ? "<{$this->_tagName}" : '';

        /** 支持自闭合 */
        if ($this->_tagName) {
            /** 输出属性 */
            foreach ($this->_attr as $name => $value) 
		    {
                $html .= (null === $value ? " {$name}" : " {$name}=\"{$value}\"");
            }
			$html .= $this->_close ? " />\n" : ">\n";
        }
		
        foreach ($this->_elements as $elements) 
		{
			if (is_array($elements)){
				foreach ($elements as $element) $html .=  (string) $element;
			} else
            $html .=  (string) $elements;
        }
		
        if ($this->_tagName && !$this->_close) {
            $html .= "</{$this->_tagName}>\n";
        }

		return $html;
    }
	
    public function  __toString() 
	{
		return $this->render();
	}	

}
